package com.red.wine.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import android.net.ParseException;

public class DateUtils {
	
	/**
     * 计算出指定的日期的将来或者过去的指定天数。
     * 
     * @param Date
     *            date 计算的基准日期
     * @param int dayNum 指定的天数
     * @param Boolean
     *            flag 若flag是true，要计算将来日期，否则，是过去日期
     * 
     * @return String compDate 计算后的日期
     */
    public static String compDate(Date date, int dayNum, Boolean flag) {
        if (!date.equals(null)) {
            // 格式化日期Date
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            String strDate = df.format(date);
            // 获取给定日期的年，月，日
            String strYear = strDate.substring(0, 4);
            int intYear = Integer.valueOf(strYear);
            String strMonth = strDate.substring(5, 7);
            int intMonth = Integer.valueOf(strMonth);
            String strDay = strDate.substring(8, 10);
            int intDay = Integer.valueOf(strDay);
            int compDay;
            // 传入的flag做出对应的将来日期计算
            if (flag) {
                // 分出月份来计算
                compDay = intDay + dayNum;
                switch (intMonth) {
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                    // 计算出的天数大于31时，天数减1，月份加1
                    if (compDay > 31) {
                        compDay = compDay - 31;
                        intMonth += 1;
                    } else if (compDay <= 31) {
                        intDay = compDay;
                    }
                    break;
                case 12:
                    if (compDay > 31) {
                        compDay = compDay - 31;
                        intMonth = 1;
                        intYear += 1;
                    } else if (compDay <= 31) {
                        intDay = compDay;
                    }
                    break;
                case 2:
                    // 闰年的二月
                    if ((intYear % 4 == 0 && intYear % 100 != 0)
                            || (intYear % 400 == 0)) {
                        if (compDay > 29) {
                            compDay = compDay - 29;
                            intMonth += 1;
                        } else if (compDay <= 29) {
                            intDay = compDay;
                        }
                    } else {
                        if (compDay > 28) {
                            compDay = compDay - 28;
                            intMonth += 1;
                        } else if (compDay <= 28) {
                            intDay = compDay;
                        }
                    }
                    break;
                case 4:
                case 6:
                case 9:
                case 11:
                    // 计算出的天数大于31时，天数减1，月份加1
                    if (compDay > 30) {
                        compDay = compDay - 30;
                        intMonth += 1;
                    } else if (compDay <= 30) {
                        intDay = compDay;
                    }
                    break;
                }

            }
            // 传入的flag做出对应过去的日期计算
            if (!flag) {
                // 分出月份来计算
                compDay = intDay - dayNum;
                switch (intMonth) {
                case 1:
                    if (compDay < 0) {
                        compDay = (intDay + 31) - dayNum;
                        intMonth = 12;
                        intYear -= 1;
                    } else if (compDay > 0) {
                        intDay = compDay;
                    } else if (compDay == 0) {
                        intDay = 31;
                        intMonth = 12;
                        intYear -= 1;
                    }
                    break;
                case 3:
                    // 闰年的二月
                    if (compDay < 0) {
                        if ((intYear % 4 == 0 && intYear % 100 != 0)
                                || (intYear % 400 == 0)) {
                            compDay = (intDay + 29) - dayNum;

                        } else {
                            compDay = (intDay + 28) - dayNum;
                        }
                        intMonth = 2;
                    } else if (compDay > 0) {
                        intDay = compDay;
                    } else if (compDay == 0) {
                        if ((intYear % 4 == 0 && intYear % 100 != 0)
                                || (intYear % 400 == 0)) {
                            intDay = 29;

                        } else {
                            intDay = 28;
                        }
                        intMonth = 2;
                    }
                    break;
                case 5:
                case 7:
                case 8:
                case 10:
                case 12:
                    // 计算出的天数小于0时，天数加上上个月的天数，在计算结果，月份减1
                    if (compDay < 0) {
                        compDay = (intDay + 30) - dayNum;
                        intMonth -= 1;
                    } else if (compDay == 0) {
                        intDay = 30;
                        intMonth -= 1;
                    } else if (compDay > 0) {
                        intDay = compDay;
                    }
                    break;
                case 2:
                case 4:
                case 6:
                case 9:
                case 11:
                    // 计算出的天数小于0时，天数加上上个月的天数，在计算结果，月份减1
                    if (compDay < 0) {
                        compDay = (intDay + 31) - dayNum;
                        intMonth -= 1;
                    } else if (compDay == 0) {
                        intDay = 31;
                        intMonth -= 1;
                    } else if (compDay > 0) {
                        intDay = compDay;
                    }
                    break;
                }

            }
            // 经过计算后的年月日拼接成字符串
            strYear = String.valueOf(intYear);
            strMonth = String.valueOf(intMonth);
            if (intMonth / 10 == 0) {
                strMonth = "0" + strMonth;
            }
            strDay = String.valueOf(intDay);
            if (intDay / 10 == 0) {
                strDay = "0" + strDay;
            }
            strDate = strYear + "-" + strMonth + "-" + strDay;
            return strDate;
        }
        return null;
    }

    /**
     * 将未指定格式的日期字符串转化成java.util.Date类型日期对象 <br>
     * 
     * @param date
     *            ,待转换的日期字符串
     * @return
     * @throws ParseException
     */
    public Date parseStringToDate(String date) throws Exception {
        Date result = null;
        String parse = date;
        parse = parse.replaceFirst("^[0-9]{4}([^0-9]?)", "yyyy$1");
        parse = parse.replaceFirst("^[0-9]{2}([^0-9]?)", "yy$1");
        parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1MM$2");
        parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}( ?)", "$1dd$2");
        parse = parse.replaceFirst("( )[0-9]{1,2}([^0-9]?)", "$1HH$2");
        parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1mm$2");
        parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1ss$2");

        SimpleDateFormat format = new SimpleDateFormat(parse);

        result = format.parse(date);

        return result;
    }

    /**
     * 计算两个日期型的时间相差多少时间
     * 
     * @param startDate
     *            开始日期
     * @param endDate
     *            结束日期
     * @return
     */
    public String twoDateDistance(Date startDate, Date endDate) {

        if (startDate == null || endDate == null) {
            return null;
        }
        long timeLong = endDate.getTime() - startDate.getTime();
        long year = timeLong / (24 * 60 * 60 * 1000 * 365);
        String yearStr = String.valueOf(year);
        long month = timeLong % (24 * 60 * 60 * 1000 * 365)
                / (24 * 60 * 60 * 1000 * 30);
        String monthStr = String.valueOf(month);
        long day = timeLong % (24 * 60 * 60 * 1000 * 365)
                % (24 * 60 * 60 * 1000 * 30) / (24 * 60 * 60 * 1000);
        String dayStr = String.valueOf(day);
        long hour = timeLong % (24 * 60 * 60 * 1000 * 365)
                % (24 * 60 * 60 * 1000 * 30) % (24 * 60 * 60 * 1000)
                / (60 * 60 * 1000);
        String hourStr = String.valueOf(hour);
        long minute = timeLong % (24 * 60 * 60 * 1000 * 365)
                % (24 * 60 * 60 * 1000 * 30) % (24 * 60 * 60 * 1000)
                % (60 * 60 * 1000) / (60 * 1000);
        String minuteStr = String.valueOf(minute);
        String returnStr = null;
        if (year != 0) {
            returnStr = yearStr + "年";
        } else if (month != 0) {
            returnStr = monthStr + "月";
        } else if (day != 0) {
            returnStr = dayStr + "天";
        } else if (hour != 0) {
            returnStr = hourStr + "小时";
        } else if (minute != 0) {
            returnStr = minuteStr + "分钟";
        }
        return returnStr==null?"1秒 前":returnStr+" 前";
    }
	/**
	 * <p>
	 * Checks if two dates are on the same day ignoring time.
	 * </p>
	 * 
	 * @param date1
	 *            the first date, not altered, not null
	 * @param date2
	 *            the second date, not altered, not null
	 * @return true if they represent the same day
	 * @throws IllegalArgumentException
	 *             if either date is <code>null</code>
	 */
	public static boolean isSameDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		return isSameDay(cal1, cal2);
	}

	/**
	 * <p>
	 * Checks if two calendars represent the same day ignoring time.
	 * </p>
	 * 
	 * @param cal1
	 *            the first calendar, not altered, not null
	 * @param cal2
	 *            the second calendar, not altered, not null
	 * @return true if they represent the same day
	 * @throws IllegalArgumentException
	 *             if either calendar is <code>null</code>
	 */
	public static boolean isSameDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA)
				&& cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1
					.get(Calendar.DAY_OF_YEAR) == cal2
				.get(Calendar.DAY_OF_YEAR));
	}

	/**
	 * <p>
	 * Checks if a date is today.
	 * </p>
	 * 
	 * @param date
	 *            the date, not altered, not null.
	 * @return true if the date is today.
	 * @throws IllegalArgumentException
	 *             if the date is <code>null</code>
	 */
	public static boolean isToday(Date date) {
		return isSameDay(date, Calendar.getInstance().getTime());
	}

	/**
	 * <p>
	 * Checks if a calendar date is today.
	 * </p>
	 * 
	 * @param cal
	 *            the calendar, not altered, not null
	 * @return true if cal date is today
	 * @throws IllegalArgumentException
	 *             if the calendar is <code>null</code>
	 */
	public static boolean isToday(Calendar cal) {
		return isSameDay(cal, Calendar.getInstance());
	}

	/**
	 * <p>
	 * Checks if the first date is before the second date ignoring time.
	 * </p>
	 * 
	 * @param date1
	 *            the first date, not altered, not null
	 * @param date2
	 *            the second date, not altered, not null
	 * @return true if the first date day is before the second date day.
	 * @throws IllegalArgumentException
	 *             if the date is <code>null</code>
	 */
	public static boolean isBeforeDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		return isBeforeDay(cal1, cal2);
	}

	/**
	 * <p>
	 * Checks if the first calendar date is before the second calendar date
	 * ignoring time.
	 * </p>
	 * 
	 * @param cal1
	 *            the first calendar, not altered, not null.
	 * @param cal2
	 *            the second calendar, not altered, not null.
	 * @return true if cal1 date is before cal2 date ignoring time.
	 * @throws IllegalArgumentException
	 *             if either of the calendars are <code>null</code>
	 */
	public static boolean isBeforeDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		if (cal1.get(Calendar.ERA) < cal2.get(Calendar.ERA))
			return true;
		if (cal1.get(Calendar.ERA) > cal2.get(Calendar.ERA))
			return false;
		if (cal1.get(Calendar.YEAR) < cal2.get(Calendar.YEAR))
			return true;
		if (cal1.get(Calendar.YEAR) > cal2.get(Calendar.YEAR))
			return false;
		return cal1.get(Calendar.DAY_OF_YEAR) < cal2.get(Calendar.DAY_OF_YEAR);
	}

	/**
	 * <p>
	 * Checks if the first date is after the second date ignoring time.
	 * </p>
	 * 
	 * @param date1
	 *            the first date, not altered, not null
	 * @param date2
	 *            the second date, not altered, not null
	 * @return true if the first date day is after the second date day.
	 * @throws IllegalArgumentException
	 *             if the date is <code>null</code>
	 */
	public static boolean isAfterDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		return isAfterDay(cal1, cal2);
	}

	/**
	 * <p>
	 * Checks if the first calendar date is after the second calendar date
	 * ignoring time.
	 * </p>
	 * 
	 * @param cal1
	 *            the first calendar, not altered, not null.
	 * @param cal2
	 *            the second calendar, not altered, not null.
	 * @return true if cal1 date is after cal2 date ignoring time.
	 * @throws IllegalArgumentException
	 *             if either of the calendars are <code>null</code>
	 */
	public static boolean isAfterDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		if (cal1.get(Calendar.ERA) < cal2.get(Calendar.ERA))
			return false;
		if (cal1.get(Calendar.ERA) > cal2.get(Calendar.ERA))
			return true;
		if (cal1.get(Calendar.YEAR) < cal2.get(Calendar.YEAR))
			return false;
		if (cal1.get(Calendar.YEAR) > cal2.get(Calendar.YEAR))
			return true;
		return cal1.get(Calendar.DAY_OF_YEAR) > cal2.get(Calendar.DAY_OF_YEAR);
	}

	/**
	 * <p>
	 * Checks if a date is after today and within a number of days in the
	 * future.
	 * </p>
	 * 
	 * @param date
	 *            the date to check, not altered, not null.
	 * @param days
	 *            the number of days.
	 * @return true if the date day is after today and within days in the future
	 *         .
	 * @throws IllegalArgumentException
	 *             if the date is <code>null</code>
	 */
	public static boolean isWithinDaysFuture(Date date, int days) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return isWithinDaysFuture(cal, days);
	}

	/**
	 * <p>
	 * Checks if a calendar date is after today and within a number of days in
	 * the future.
	 * </p>
	 * 
	 * @param cal
	 *            the calendar, not altered, not null
	 * @param days
	 *            the number of days.
	 * @return true if the calendar date day is after today and within days in
	 *         the future .
	 * @throws IllegalArgumentException
	 *             if the calendar is <code>null</code>
	 */
	public static boolean isWithinDaysFuture(Calendar cal, int days) {
		if (cal == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar today = Calendar.getInstance();
		Calendar future = Calendar.getInstance();
		future.add(Calendar.DAY_OF_YEAR, days);
		return (isAfterDay(cal, today) && !isAfterDay(cal, future));
	}

	/** Returns the given date with the time set to the start of the day. */
	public static Date getStart(Date date) {
		return clearTime(date);
	}

	/** Returns the given date with the time values cleared. */
	public static Date clearTime(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}

	/**
	 * Determines whether or not a date has any time values (hour, minute,
	 * seconds or millisecondsReturns the given date with the time values
	 * cleared.
	 */

	/**
	 * Determines whether or not a date has any time values.
	 * 
	 * @param date
	 *            The date.
	 * @return true iff the date is not null and any of the date's hour, minute,
	 *         seconds or millisecond values are greater than zero.
	 */
	public static boolean hasTime(Date date) {
		if (date == null) {
			return false;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		if (c.get(Calendar.HOUR_OF_DAY) > 0) {
			return true;
		}
		if (c.get(Calendar.MINUTE) > 0) {
			return true;
		}
		if (c.get(Calendar.SECOND) > 0) {
			return true;
		}
		if (c.get(Calendar.MILLISECOND) > 0) {
			return true;
		}
		return false;
	}

	/** Returns the given date with time set to the end of the day */
	public static Date getEnd(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MILLISECOND, 999);
		return c.getTime();
	}

	/**
	 * Returns the maximum of two dates. A null date is treated as being less
	 * than any non-null date.
	 */
	public static Date max(Date d1, Date d2) {
		if (d1 == null && d2 == null)
			return null;
		if (d1 == null)
			return d2;
		if (d2 == null)
			return d1;
		return (d1.after(d2)) ? d1 : d2;
	}

	/**
	 * Returns the minimum of two dates. A null date is treated as being greater
	 * than any non-null date.
	 */
	public static Date min(Date d1, Date d2) {
		if (d1 == null && d2 == null)
			return null;
		if (d1 == null)
			return d2;
		if (d2 == null)
			return d1;
		return (d1.before(d2)) ? d1 : d2;
	}

	public static Long TimeInMillis(Date d1) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(d1);
		return Calendar.getInstance().getTimeInMillis();
	}

	/** The maximum date possible. */
	public static Date MAX_DATE = new Date(Long.MAX_VALUE);
}
